using System;
using System.Collections;
using System.Collections.Generic;
using MEC;
using UnityEngine;
using YooAsset;

#pragma warning disable 0219

/// <summary>
/// User interface manager.
/// </summary>
public class UIManager : Singleton_UI<UIManager>
{
    #region UI对象的信息类   UIInfoData class
    /// <summary>
    /// 需要打开UI界面时，传入的UI对象的信息类
    /// </summary>
    class UIInfoData
    {
        // UI类型，不需要在外面访问，set设成私有的
        public EnumUIType UIType { get; private set; }

        // 该UI对应的脚本的类型 
        public Type ScriptType { get; private set; }

        // UI的存储路径
        public string Path { get; private set; }

        // UI 可变参数
        public Dictionary<EnumUIType, object> UIParams { get; private set; }



        // 构造函数，参数：ui类型，路径，可变参数
        public UIInfoData(EnumUIType _uiType, string _path, Dictionary<EnumUIType, object> _uiParams)
        {
            this.UIType = _uiType;
            this.Path = _path;
            this.UIParams = _uiParams;
            this.ScriptType = UIPathDefines.GetUIScriptByType(this.UIType);//取得该UI类型对应的脚本的Type
        }
    }
    #endregion


    /// <summary>
    /// 保存已经打开的UI的集合
    /// </summary>
    private Dictionary<EnumUIType, GameObject> dicOpenUIs = null;

    private GameObject MainUIObj = null;
    public GameObject Community1, Community2;
    /// <summary>
    /// 将需要打开的UI的集合，泛型类是 UIInfoData
    /// System.Collections.Stack类表示对象的简单的后进先出非泛型集合。
    /// 堆栈（Stack）代表了一个后进先出的对象集合
    /// </summary>
    private Stack<UIInfoData> stackOpenUIs = null;

    /// <summary>
    /// 初始化函数
    /// </summary>
    public override void Init()
    {
        dicOpenUIs = new Dictionary<EnumUIType, GameObject>();    // 初始化保存已经打开的UI的集合
        stackOpenUIs = new Stack<UIInfoData>();                   // 初始化将需要打开的UI的集合
    }
   
    #region 获取指定类型的UI  Get UI & UIObject By EnunUIType
    /// <summary>
    /// 获取指定类型的UI
    /// <typeparam name="T">The 1st type parameter.</typeparam>
    public T GetUI<T>(EnumUIType _uiType) where T : BaseUI
    {
        GameObject _retObj = GetUIObject(_uiType);
        if (_retObj != null)
        {
            return _retObj.GetComponent<T>();
        }
        return null;
    }

    /// <summary>
    /// 在 “已经打开的UI的集合” 中获取特定类型的UI
    /// </summary>
    public GameObject GetUIObject(EnumUIType _uiType)
    {
        GameObject _retObj = null;
        if (!dicOpenUIs.TryGetValue(_uiType, out _retObj))
            throw new Exception("dicOpenUIs TryGetValue Failure! _uiType :" + _uiType.ToString());
        return _retObj;
    }
    #endregion

    public bool IsHaveUI(EnumUIType _uiType)
    {
        GameObject _retObj = null;
        dicOpenUIs.TryGetValue(_uiType, out _retObj);
        return null != _retObj;
    }

    public T TryGetUI<T>(EnumUIType _uiType) where T : BaseUI
    {
        GameObject _retObj = null;
        dicOpenUIs.TryGetValue(_uiType, out _retObj);
        if (_retObj != null)
        {
            return _retObj.GetComponent<T>();
        }
        return null;
    }
    

    #region 打开UI界面。Open UI By EnumUIType
    /// <summary>
    /// 打开UI界面。
    /// 重载函数，打开 一组 的UI。
    /// #### 但不关闭 ####
    /// </summary>
    public void OpenUI(EnumUIType uiType,bool _needTween)
    {
        Debug.Log("OPENMAIN");
        
        EnumUIType[] uiTypes = new EnumUIType[1];//EnumUIType.MessageBoxWnd
        uiTypes[0] = uiType;
        
        if (uiType == EnumUIType.MessageBoxWnd)//如果是消息框
        {
            CloseUI(EnumUIType.MessageBoxWnd);
            OpenUI(false, uiTypes, 3,_needTween, null);
        }
        //else if (uiType == EnumUIType.MainUIWnd)//主界面
        //{
           
        //    // 打开，但不关闭
        //    OpenUI(false, uiTypes, null, null);
        //}
        else
        {
            // 打开，但不关闭
            OpenUI(false, uiTypes, null,_needTween, null);
        }
    }
    // 字典参数更灵活
    public void OpenUI(EnumUIType uiType,bool _needTween, Dictionary<EnumUIType, object> uiParams = null)
    {
        // 处理打开UI的逻辑，传递字典参数
        // 示例：
        OpenUI(false, new EnumUIType[] { uiType }, null,_needTween, uiParams);
    }

    /// <summary>
    /// 打开UI界面。
    /// 重载函数，打开 一组 的UI。
    /// #### 但不关闭 ####
    /// </summary>
    public void OpenUI(EnumUIType uiType, object canvas,bool _needTween)
    {
        EnumUIType[] uiTypes = new EnumUIType[1];
        uiTypes[0] = uiType;

        // 打开，但不关闭
        OpenUI(false, uiTypes, canvas,_needTween, null);
 
    }

    /// <summary>
    /// 打开UI界面。
    /// 重载函数，打开 单个 的UI，就可以传参数了
    /// #### 但不关闭 ####
    /// </summary>
    public void OpenUI(EnumUIType uiType, object canvas,bool _needTween, Dictionary<EnumUIType, object> uiObjParams)
    {
        // 因为 OpenUI 主函数参数为：EnumUIType[] _uiTypes，此处为：EnumUIType uiType，需做个转换。
        EnumUIType[] uiTypes = new EnumUIType[1];
        uiTypes[0] = uiType;
        OpenUI(false, uiTypes, canvas,_needTween, uiObjParams);
    }

    /// <summary>
    /// 打开UI界面。
    /// 重载函数，打开 一组 的UI。
    /// #### 同时关闭其他UI. ####
    /// </summary>
    /// <param name="uiTypes">User interface types.</param>
    public void OpenUICloseOthers(EnumUIType[] uiTypes,bool _needTween)
    {
        OpenUI(true, uiTypes, null,_needTween, null);
    }

    /// <summary>
    /// 打开UI界面。
    /// 重载函数，打开 单个 的UI，就可以传参数了
    /// #### 同时关闭其他UI. ####
    /// <param name="uiObjParams">User interface object parameters.</param>
    public void OpenUICloseOthers(EnumUIType uiType, Dictionary<EnumUIType, object> uiObjParams,bool _needTween)
    {
        // 因为 OpenUI 主函数参数为：EnumUIType[] _uiTypes，此处为：EnumUIType uiType，需做个转换。 
        EnumUIType[] uiTypes = new EnumUIType[1];
        uiTypes[0] = uiType;
        OpenUI(true, uiTypes, null,_needTween, uiObjParams);
    }

    /// <summary>
    /// 打开UI，参数：是否需要关闭其他UI, UI类型数组（可以打开了多个UI），不定长的数组参数
    /// </summary>
    private void OpenUI(bool _isCloseOthers, EnumUIType[] _uiTypes, object canvas, bool _needTween, Dictionary<EnumUIType, object> uiParams = null)
    {
        // 如果关闭其他UI
        if (_isCloseOthers)
        {
            CloseUIAll();        // 关闭其他UI
        }
        

        // 添加 _uiTypes到 Stack<UIInfoData> stackOpenUIs
        // Dictionary.ContainsKey 方法 , 如果 Dictionary 包含具有指定键的元素，则为 true；否则为 false。
        //foreach (KeyValuePair<EnumUIType, GameObject> kvp in dicOpenUIs)
        //{
        //    Debug.Log("Key = " + kvp.Key + " Value = " + kvp.Value);
        //}

        // “庇护”时期添加的开启ui时候加的动画
        //UnityEngine.Object _animPrefab;
        //_animPrefab = Resources.Load("Prefabs/OpenUIAnim");
        //GameObject _animObj = UnityEngine.Object.Instantiate(_animPrefab) as GameObject;

        //_animObj.transform.SetParent(ComFuncAttForUI.GetCanvasForScene(canvas).transform);

        for (int i = 0; i < _uiTypes.Length; i++)
        {
            EnumUIType _uiType = _uiTypes[i];
            // 判断已经打开的UI集合里是否有该类型的UI
            // 如果没有打开，则把它加到需要打开的集合 stackOpenUIs 里面

            if (!dicOpenUIs.ContainsKey(_uiType))
            {
                // 得到UI 在项目中的存放路径
                string _path = UIPathDefines.GetPrefabPathByType(_uiType);
                // Push表示向 Stack 的顶部添加一个对象。此为一个UIInfoData类型的对象
                stackOpenUIs.Push(new UIInfoData(_uiType, _path, uiParams));
            }
            
        }

        // 打开UI
        // 如果Stack堆栈中有 UI类型
        // 此处资源加载，要考虑是同步还是异步加载
        if (stackOpenUIs.Count > 0 && stackOpenUIs.Count < 2)
        {
            Timing.RunCoroutine(AsyncLoadData(canvas, _needTween));
        }
    }

    // “保安”改良新手引导对应逻辑做的代码，看情况解注
    //public bool IsGuiding()
    //{
    //    if (null != TryGetUI<RookieGuideUIWnd>(EnumUIType.RookieGuideUIWnd))
    //        return true;
    //    if (null != TryGetUI<RookieJianliGuideUIWnd>(EnumUIType.RookieJianliGuideUIWnd))
    //        return true;
    //    if (null != TryGetUI<RookieDepartmentGuideUIWnd>(EnumUIType.RookieDepartmentGuideUIWnd))
    //        return true;
    //    if (null != TryGetUI<RookieBuildIncomeMultipleGuideUIWnd>(EnumUIType.RookieBuildIncomeMultipleGuideUIWnd))
    //        return true;
    //    if (null != TryGetUI<RookieBattleLvGuideUIWnd>(EnumUIType.RookieBattleLvGuideUIWnd))
    //        return true;
    //    return false;
    //}


    /// <summary>
    /// 加载UI对象
    /// </summary>
    /// <returns></returns>
    private IEnumerator<float> AsyncLoadData(object canvas,bool NeedTween)
    {
        UIInfoData _uiInfoData = null;
        GameObject _prefabObj = null;
        GameObject _uiObject = null;

        while (stackOpenUIs.Count > 0)
        {
            _uiInfoData = stackOpenUIs.Pop();
            bool isLoaded = false;
            GameObject _uiAnimObj = null;

            // 是否需要播放开启UI的动画
            if (NeedTween)
            {
                //在加载ui之前先把ui过渡动画加上
                var _uiAnimprefab = Resources.Load(Defines.UILoadingTweenPath);//部分ui界面动画的预制体;//部分ui界面动画的预制体
                

                GameObject _uiAnimCanvas = GameObject.FindWithTag("LoadCanvas");
                _uiAnimObj = MonoBehaviour.Instantiate(_uiAnimprefab, _uiAnimCanvas.transform) as GameObject;

                yield return Timing.WaitUntilTrue(() => _uiAnimObj != null);
                _uiAnimObj.transform.localPosition = Vector3.zero;

                yield return Timing.WaitUntilTrue(() => (_uiAnimObj.GetComponent<UITransitionTween>().isLoadinDone));
            }
            
            AssetHandle handle = YooAssets.LoadAssetAsync<GameObject>(_uiInfoData.Path);
            yield return Timing.WaitUntilTrue(()=>(handle.Status != EOperationStatus.Processing));
            if (handle.Status == EOperationStatus.Succeed)
            {
                _prefabObj = handle.AssetObject as GameObject;
                _uiObject = MonoBehaviour.Instantiate(_prefabObj);

                yield return Timing.WaitUntilTrue(()=> (_uiObject != null));
            } else
            {
                Debug.LogWarning("UI_Bundle Load is warning");
                yield break;
            }

            // 确保实例化成功后再进行后续操作
            if (_uiObject != null)
            {
                _uiObject.transform.SetParent(GetCanvasForScene(canvas).transform);

                if (_uiObject.GetComponent<AdaptiveWnds>() == null)
                    _uiObject.AddComponent<AdaptiveWnds>();

                _uiObject.gameObject.GetComponent<RectTransform>().offsetMax = new Vector2(0, 0);
                _uiObject.gameObject.GetComponent<RectTransform>().offsetMin = new Vector2(0, 0);

                BaseUI _baseUI = _uiObject.GetComponent<BaseUI>();
                if (_baseUI == null)
                {
                    _baseUI = _uiObject.AddComponent(_uiInfoData.ScriptType) as BaseUI;
                }
                if (_baseUI != null)
                {
                    _baseUI.SetUIWhenOpening(_uiInfoData.UIParams);
                }
                dicOpenUIs.Add(_uiInfoData.UIType, _uiObject);

                // 过渡动画的关闭
                if(_uiAnimObj != null)
                    _uiAnimObj.GetComponent<UITransitionTween>().LoadingOut();
            }
        }
    }

    public const int canvasNum = 4;//场景里canvas的数量        mGameObject.transform.childCount
    /// <summary>
    /// 获得场景里的 Canvas
    /// </summary>
    /// <returns></returns>
    public GameObject GetCanvasForScene(object _uiParams)
    {
        GameObject canvas = GameObject.FindGameObjectWithTag("Canvas");
        if (_uiParams == null)
        {
            Debug.Log($"bundle.controller.findtag:{canvas.name}");
            return canvas;
        }
        else
        {
            int index = int.Parse(_uiParams.ToString());
            //加个判断 类型
            if (index >= 1 || index <= (canvasNum - 1))
            {
                canvas = GameObject.Find("Canvas" + _uiParams);
            }
            else return GameObject.Find("Canvas" + (canvasNum - 1));
        }
        return canvas;
    }

    IEnumerator PreLoadFrefab(string path)
    {
        ResourceRequest request = Resources.LoadAsync(path);
        yield return request;

        if (request.asset != null)
        {
            var prefabObj = request.asset as GameObject;

            if (path.Contains("MainUIWnd"))
            {
                MainUIObj = prefabObj;
            }
            if(path.Contains("Comm001"))
            {
                Community1 = prefabObj;
            }
            if (path.Contains("Comm002"))
            {
                Community2 = prefabObj;
            }
            Debug.Log("PreLoadFrefab: " + prefabObj.name);
        }
        else
        {
            Debug.LogError("PreLoadFrefabFailed: " + path);
        }
    }
    #endregion


    #region 关闭UI界面  Close UI By EnumUIType
    /// <summary>
    /// 关闭界面。
    /// 通过EnumUIType
    /// </summary>
    /// <param name="uiType">User interface type.</param>
    public void CloseUI(EnumUIType _uiType)
    {
        GameObject _uiObj = null;
      
        // 判断已经打开的UI的集合中，是否有该类型的UI对象，有的话往下进行关闭操作，没有则返回。
        // TryGetValue 获取与指定键关联的值。返回值为bool
        // 如果 true 包含具有指定键的元素；否则为 false。
        if (!dicOpenUIs.TryGetValue(_uiType, out _uiObj))
        {
            //Debug.Log("dicOpenUIs TryGetValue Failure! _uiType :" + _uiType.ToString());
            return;
        }
        // 关闭该UI
        CloseUI(_uiType, _uiObj);
    }

    /// <summary>
    /// 关闭一组UI
    /// </summary>
    public void CloseUI(EnumUIType[] _uiTypes)
    {
        for (int i = 0; i < _uiTypes.Length; i++)
        {
            CloseUI(_uiTypes[i]);
        }
    }

    /// <summary>
    /// 关闭所有UI界面
    /// </summary>
    public void CloseUIAll()
    {
        List<EnumUIType> _keyList = new List<EnumUIType>(dicOpenUIs.Keys);    // 泛型实例化，下有注解
        // 循环实现所有的已经打开的UI全部关闭
        for (int i=0;i<_keyList.Count;i++)
        {
            GameObject _uiObj = dicOpenUIs[_keyList[i]];
            CloseUI(_keyList[i], _uiObj);
        }
        dicOpenUIs.Clear();//清空已经打开的UI的集合
    }

    /// <summary>
    /// 关闭UI 的主函数
    /// </summary>
    /// <param name="_uiType"></param>
    /// <param name="_uiObj"></param>
    private void CloseUI(EnumUIType _uiType, GameObject _uiObj)
    {
        if (_uiObj == null)
        {
            dicOpenUIs.Remove(_uiType);   // 已经打开的UI的集合  中 移除
        }
        else
        {
            BaseUI _baseUI = _uiObj.GetComponent<BaseUI>();
            if (_baseUI != null)
            {
                _baseUI.StateChanged += CloseUIHandler;
                _baseUI.Release();//释放，关闭UI
            }
            else
            {
                GameObject.Destroy(_uiObj);
                dicOpenUIs.Remove(_uiType);
            }
        }
        //if (dicOpenUIs.Count == 1 && dicOpenUIs.ContainsKey(EnumUIType.MainUIWnd))
        //{
        //    if (TimeManageController.Instance != null)
        //        TimeManageController.Instance.GameTimeReStart();
        //}
    }

    /// <summary>
    /// 关闭UI的逻辑
    /// </summary>
    private void CloseUIHandler(object _sender, EnumObjectState _newState, EnumObjectState _oldState)
    {
        if (_newState == EnumObjectState.Closing)//当新的状态为关闭时
        {
            BaseUI _baseUI = _sender as BaseUI;// BaseUI里属性里调用委托，参数为BaseUI
            dicOpenUIs.Remove(_baseUI.GetUIType());// 在已打开里移除
            _baseUI.StateChanged -= CloseUIHandler;// 在事件里移除
        }
    }
    #endregion
}





